package pro.cherish.smartfile.test.file;

import cn.hutool.core.util.RandomUtil;
import io.swagger.annotations.Api;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import pro.cherish.smartfile.common.exception.BusinessException;
import pro.cherish.smartfile.util.Md5Util;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.Future;

/**
 * @author 创建人：lys
 * @version 版本号：V1.0
 * <p>
 * ***************************修订记录************************************
 * 2020-12-01 lys 创建该类功能。
 * **********************************************************************
 * </p>
 * @ClassName 类名：IndexController
 * @Description 功能说明：
 * <p>
 *
 * </p>
 * **********************************************************************
 * @date 创建日期： 2020-12-01 lys
 */

@RestController
@RequestMapping("/api/v1/home")
@Api(tags = "工具")
@Slf4j
public class IndexController {
//
//    @GetMapping("")
//    public Mono<Result> home(ServerWebExchange serverWebExchange) {
//        ServerHttpRequest request = serverWebExchange.getRequest();
//        DecoderHttpMessageReader<byte[]> httpMessageReader = new DecoderHttpMessageReader(new ByteArrayDecoder());
//        ResolvableType resolvableType = ResolvableType.forClass(byte[].class);
//        Mono<byte[]> mono = httpMessageReader.readMono(resolvableType, request, Collections.emptyMap());
//        String body = mono.map(bytes -> new String(bytes)).block();
//        return Mono.just(Result.ok("welcome to cherish file!"));
//    }
//    @SneakyThrows
//    @PostMapping(value = "/file")
//    public Mono<Result> file(ServerWebExchange exchange) {
//        return Mono.just(Result.ok());
//    }
//
//
//    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
//    public Mono<String> requestBodyFlux(@RequestPart("file") FilePart filePart) throws IOException {
//        File targetFile = FileUtil.createTempFile(new File("D:\\tmp\\"));
//        Path path = targetFile.toPath();
//        //NOTE 方法一
//        AsynchronousFileChannel channel =
//                AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
//        Flux<DataBuffer> content = filePart.content();
//        content.subscribe(buffer -> {
//            byte[] bytes = new byte[buffer.readableByteCount()];
//            buffer.read(bytes);
//            DataBufferUtils.release(buffer);
//            try {
//                String bodyString = new String(bytes, "utf-8");
//                System.out.println(bodyString);
//            } catch (UnsupportedEncodingException e) {
//                e.printStackTrace();
//            }
//        });
//        DataBufferUtils.write(content, channel, 0)
//                .doOnComplete(() -> {
//                    System.out.println("finish");
//                })
//                .subscribe();
//        //NOTE 方法二
//        return Mono.just(filePart.filename());
//    }


    @GetMapping("tx")
    public void tx() throws Exception {
        Path path = Paths.get("D:\\temp\\a.txt");
        path.toFile().createNewFile();
        AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);

        ByteBuffer buffer = ByteBuffer.allocate(1024);
        long position = 0;

        buffer.put("test data".getBytes());
        buffer.flip();

        Future<Integer> operation = fileChannel.write(buffer, position);
        buffer.clear();

        while (!operation.isDone()) {
            ;
        }

        System.out.println("Write done");
    }

    @GetMapping("tx2")
    public void tx2() throws Exception {
        Path path = Paths.get("D:\\temp\\a.txt");
        path.toFile().createNewFile();
        if (!Files.exists(path)) {
            Files.createFile(path);
        }
        AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);

        ByteBuffer buffer = ByteBuffer.allocate(1024);
        long position = 0;

        buffer.put("test data".getBytes());
        buffer.flip();

        fileChannel.write(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>() {

            @Override
            public void completed(Integer result, ByteBuffer attachment) {
                System.out.println("bytes written: " + result);
            }

            @Override
            public void failed(Throwable exc, ByteBuffer attachment) {
                System.out.println("Write failed");
                exc.printStackTrace();
            }
        });
    }

    @GetMapping("tx3")
    public void tx3() throws Exception {
        int a = 1;
        if (a == 1) {
            throw new BusinessException("xxxx");
        }
        Path path = Paths.get("D:\\temp\\a.txt");
        path.toFile().createNewFile();
        if (!Files.exists(path)) {
            Files.createFile(path);
        }
        AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);

        ByteBuffer buffer = ByteBuffer.allocate(1024);
        long position = 0;

        buffer.put("test data".getBytes());
        buffer.flip();

        fileChannel.write(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>() {

            @Override
            public void completed(Integer result, ByteBuffer attachment) {
                System.out.println("bytes written: " + result);
            }

            @Override
            public void failed(Throwable exc, ByteBuffer attachment) {
                System.out.println("Write failed");
                exc.printStackTrace();
            }
        });
    }

    @GetMapping("tt")
    public void test() throws Exception {
        byte[] bytes = RandomUtil.randomBytes(1025);
        ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
        File file = new File("D:\\temp\\a.txt");
        file.createNewFile();
        log.info("主线程，线程{}", Thread.currentThread().getId());
        AsynchronousFileChannel channel = AsynchronousFileChannel.open(file.toPath(), StandardOpenOption.WRITE);
        channel.write(byteBuffer, 0, byteBuffer, new CompletionHandler<Integer, ByteBuffer>() {
            @SneakyThrows
            @Override
            public void completed(Integer result, ByteBuffer attachment) {
                log.info("completed，线程{}", Thread.currentThread().getId());
                try {
                    channel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                log.info("关闭后，文件是否占用{}", channel.isOpen());
                byteBuffer.flip();
            }

            @Override
            public void failed(Throwable exc, ByteBuffer attachment) {
                log.info("failed，线程{}", Thread.currentThread().getId());
            }
        });
        log.info("最后，线程{}", Thread.currentThread().getId());
        // 读取文件，查看md5
        log.error("md5:{}", Md5Util.file2Md5(file));
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.error("md5:{}", Md5Util.file2Md5(file));
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
